package org.terramagnet.mvcframework.resource.controller;

import org.terramagnet.mvcframework.resource.ResourceArchive;
import org.terramagnet.mvcframework.tools.SpringMvcUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.terramagnet.mvcframework.query.Query;
import org.terramagnet.mvcframework.query.QueryHolder;
import org.terramagnet.mvcframework.resource.ResourceService;
import org.terramagnet.mvcframework.tools.Paginal;

/**
 * 资源服务器对外URL.
 *
 * <p>
 * 资源服务应使用{@code RESTfull API}，web.xml配置如下：</p><pre><code>
 * &lt;servlet&gt;
 *     &lt;servlet-name&gt;kjm-resource&lt;/servlet-name&gt;
 *     &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
 *     &lt;init-param&gt;
 *         &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
 *         &lt;param-value&gt;classpath:kjm-resource-servlet.xml&lt;/param-value&gt;
 *     &lt;/init-param&gt;
 *     &lt;load-on-startup&gt;8&lt;/load-on-startup&gt;
 * &lt;/servlet&gt;
 * &lt;servlet-mapping&gt;
 *     &lt;servlet-name&gt;kjm-resource&lt;/servlet-name&gt;
 *     &lt;url-pattern&gt;/rest/*&lt;/url-pattern&gt;
 * &lt;/servlet-mapping&gt;</code></pre>
 *
 * <p>
 * {@code kjm-resource-servlet.xml}中必须如下配置以支持{@code RESTfull API}：</p><pre><code>
 * &lt;mvc:annotation-driven&gt;
 *     &lt;mvc:path-matching suffix-pattern="false" /&gt;
 * &lt;/mvc:annotation-driven&gt;</code></pre>
 *
 * @author terrason
 */
@Controller
public class ResourceController {

    @Resource
    private ResourceService resourceService;
    @Resource
    private QueryHolder queryHolder;

    @RequestMapping(value = "/{key:.+}", method = RequestMethod.GET)
    public String view(@PathVariable String key) {
        ResourceArchive resource = resourceService.view(key, true);
        if (resource == null) {
            if (key.startsWith("rest/")) {
                key = key.substring(5);
            }
            return "redirect:/" + key;
        }
        String path = resource.getUrl();
        int last = path.lastIndexOf("/");
        String lastPath;
        try {
            lastPath = URLEncoder.encode(path.substring(last + 1), "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException("UTF-8 URLEncode error", ex);//this cannot happen
        }
        return "redirect:" + path.substring(0, last + 1) + lastPath;
    }

    @RequestMapping(value = "/**", method = RequestMethod.GET)
    public String view() {
        return view(SpringMvcUtils.currentRequestUrl().substring(1));
    }

    /**
     * 上传新文件. 新建的资源是临时的。
     *
     * @param file 上传的文件
     * @param bucket 资源桶 资源桶用于对资源进行业务分组.
     * @param spliter 上传多个文件时，返回的KEY值分隔符。
     */
    @RequestMapping(value = "/", headers = "content-type=multipart/*", method = RequestMethod.POST)
    @ResponseBody
    public String upload(@RequestParam MultipartFile[] file,
        String bucket,
        @RequestParam(defaultValue = ",") String spliter) throws IOException {
        List<String> keys = resourceService.create(bucket, file);

        return StringUtils.join(keys, spliter);
    }

    /**
     * 连接资源. 连接后的资源不再是临时的。
     */
    @RequestMapping(value = "/{key:.+}", method = RequestMethod.PUT)
    public ResponseEntity link(@PathVariable String key, String module, String principal) {
        resourceService.link(key, module, principal);
        return new ResponseEntity(HttpStatus.OK);
    }

    /**
     * 删除资源.
     */
    @RequestMapping(value = "/{key:.+}", method = RequestMethod.DELETE)
    public ResponseEntity delete(@PathVariable String key) {
        ResourceArchive resource = resourceService.view(key, false);
        if (resource == null || !resource.isLocalResource()) {
            return new ResponseEntity(HttpStatus.NO_CONTENT);
        }
        resourceService.delete(key);
        return new ResponseEntity(HttpStatus.OK);
    }

    /**
     * 删除多个资源.
     */
    @RequestMapping(value = "/", method = RequestMethod.DELETE)
    public ResponseEntity batchDelete(@RequestParam String keys) {
        if (StringUtils.isBlank(keys)) {
            return new ResponseEntity(HttpStatus.NO_CONTENT);
        }
        String[] ks = keys.split("[,;|]");
        resourceService.delete(ks);
        return new ResponseEntity(HttpStatus.OK);
    }
    

    @RequestMapping(path = "/search", method = RequestMethod.POST)
    public String serach(@RequestParam MultiValueMap<String,String> params) {
        queryHolder.saveRequestParameters(getClass().getName(), params);
        return "redirect:/";
    }
    
    
    @RequestMapping(path = "/", method = RequestMethod.GET)
    @ResponseBody
    public Paginal resource(@RequestParam MultiValueMap<String,String> params) {
        Query query = queryHolder.query(getClass().getName());
        int page = query.getPositiveIntParameter("page", 1);
        int size = query.getPositiveIntParameter("size", 12);
        Paginal<ResourceArchive> paginal = resourceService.page(null, null, null, page,size);
        return paginal;
    }
}
